//
//  JHAssetsBrowserViewController.m
//  JHAssetsPhotoPickerViewController
//
//  Created by admin on 15/11/18.
//  Copyright © 2015年 mohe. All rights reserved.
//

#import "JHAssetsBrowserViewController.h"
#import "JHAssetsCollectionManager.h"
#import "JHZoomingScrollView.h"
#import "JHAssetsManager.h"
#import "PopAnimator.h"
#import "UIImage+JHAssetsPicker.h"

#define PADDING                  10

@interface JHAssetsBrowserViewController ()<UIScrollViewDelegate, UINavigationControllerDelegate>
{
    NSMutableSet *_visiblePages, *_recycledPages;
}
@property (nonatomic, strong) PHCachingImageManager *imageManager;
@end

@implementation JHAssetsBrowserViewController
#pragma mark Init
- (void)initialisation {
    
    // Defaults
    NSNumber *isVCBasedStatusBarAppearanceNum = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"];
    if (isVCBasedStatusBarAppearanceNum) {
        _isVCBasedStatusBarAppearance = isVCBasedStatusBarAppearanceNum.boolValue;
    } else {
        _isVCBasedStatusBarAppearance = YES; // default
    }
    _viewIsActive = NO;
    _statusBarShouldBeHidden = NO;
    _visiblePages = [NSMutableSet set];
    _recycledPages = [NSMutableSet set];
    self.imageManager = [[PHCachingImageManager alloc]init];
}
#pragma mark - Layout
- (void)performLayout {
    
    self.view.clipsToBounds = YES;
    self.automaticallyAdjustsScrollViewInsets = NO;
    _pagingScrollView = [[UIScrollView alloc] initWithFrame:[self frameForPagingScrollView]];
    _pagingScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    _pagingScrollView.pagingEnabled = YES;
    _pagingScrollView.delegate = self;
    _pagingScrollView.showsHorizontalScrollIndicator = NO;
    _pagingScrollView.showsVerticalScrollIndicator = NO;
    [_pagingScrollView setBackgroundColor:[UIColor whiteColor]];
    [self.view addSubview:_pagingScrollView];
    
    if(self.displaySelectionButtons){
        _selectedButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _selectedButton.contentMode = UIViewContentModeTopRight;
        _selectedButton.adjustsImageWhenHighlighted = NO;
        [_selectedButton setImage:[UIImage imageForResourcePath:@"JHAssetsBrowser.bundle/ImageSelectedSmallOff" ofType:@"png" inBundle:[NSBundle bundleForClass:[self class]]] forState:UIControlStateNormal];
        [_selectedButton setImage:[UIImage imageForResourcePath:@"JHAssetsBrowser.bundle/ImageSelectedSmallOn" ofType:@"png" inBundle:[NSBundle bundleForClass:[self class]]] forState:UIControlStateSelected];
        [_selectedButton addTarget:self action:@selector(selectionButtonPressed) forControlEvents:UIControlEventTouchDown];
        [_selectedButton setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, -10)];
        _selectedButton.frame = CGRectMake(0, 0, 31, 31);
       // [self.view addSubview:_selectedButton];
        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:_selectedButton];
    }else{
        UIBarButtonItem *doneItem = [[UIBarButtonItem alloc]initWithTitle:@"完成" style:UIBarButtonItemStylePlain target:self action:@selector(donePickViewController)];
        self.navigationItem.rightBarButtonItem = doneItem;
    }
    

    [self updateNavTitle];
    
    _pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:_currentIndex];
}
- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    for (JHZoomingScrollView *page in _visiblePages) {
        NSUInteger index = page.index;
        page.frame = [self frameForPageAtIndex:index];
    }
    _pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
    _pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:_currentIndex];
    [self startPageAtIndex:_currentIndex];
    [self tilePages];
}
#pragma mark - Appearance
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self displaySelectionButton];
}
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
     self.navigationController.delegate = self;
    _viewIsActive = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:YES];
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}

#pragma mark - View Loading

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self initialisation];
    [self performLayout];
}

- (void)startPageAtIndex:(NSUInteger)index
{
    if (![self numberOfPhotos]) {
        // Show controls
        [self setControlsHidden:NO animated:YES];
        return;
    }
    NSMutableArray *startArray = [NSMutableArray array];
    [startArray addObject:self.assetArray[index]];
    if(index == 0 &&self.assetArray.count > 1){
        [startArray addObject:self.assetArray[1]];
    }else if (index == self.assetArray.count-1){
        [startArray addObject:self.assetArray[self.assetArray.count-1]];
    }else{
        [startArray addObject:self.assetArray[index-1]];
        [startArray addObject:self.assetArray[index+1]];
    }
    
    NSMutableArray *stopArray = [NSMutableArray array];
    if(index == 0 &&self.assetArray.count > 2){
        [stopArray addObject:self.assetArray[2]];
    }else if (index == (self.assetArray.count-1) && self.assetArray.count>2){
        [stopArray addObject:self.assetArray[self.assetArray.count-2]];
    }else{
        if(((NSInteger)index-2)>0){
            [stopArray addObject:self.assetArray[index-2]];
        }else if((index+2)<=(self.assetArray.count-1)){
            [stopArray addObject:self.assetArray[index+2]];

        }
    }
    [self.imageManager startCachingImagesForAssets:startArray
                                        targetSize:[JHAssetsManager sizeOfPreview]
                                       contentMode:PHImageContentModeAspectFill
                                           options:[JHAssetsManager previewRequestOptions]];
    if(stopArray.count){
        [self.imageManager stopCachingImagesForAssets:stopArray
                                           targetSize:[JHAssetsManager sizeOfPreview]
                                          contentMode:PHImageContentModeAspectFill
                                              options:[JHAssetsManager previewRequestOptions]];
    }
    
}

- (void)updateNavTitle
{
    self.title = [NSString stringWithFormat:@"%lu / %li", (unsigned long)_currentIndex+1, (long)_photoCount];
}
- (void)jumpToPageAtIndex:(NSUInteger)index animated:(BOOL)animated {
    
    // Change page
    if (index < [self numberOfPhotos]) {
        CGRect pageFrame = [self frameForPageAtIndex:index];
        [_pagingScrollView setContentOffset:CGPointMake(pageFrame.origin.x - PADDING, 0) animated:animated];
    }
}

- (void)setCurrentIndex:(NSUInteger)currentIndex {
    // Validate
    _selectedIndex = currentIndex;
    NSUInteger photoCount = [self numberOfPhotos];
    if (photoCount == 0) {
        currentIndex = 0;
    } else {
        if (currentIndex >= photoCount)
            currentIndex = [self numberOfPhotos]-1;
    }
    _currentIndex = currentIndex;
    if ([self isViewLoaded]) {
        [self jumpToPageAtIndex:currentIndex animated:NO];
        if (!_viewIsActive)
            [self tilePages]; // Force tiling if view is not visible
    }
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if(!_viewIsActive) return;
    [self tilePages];
    CGRect visibleBounds = _pagingScrollView.bounds;
    NSInteger index = (NSInteger)(floorf(CGRectGetMidX(visibleBounds) / CGRectGetWidth(visibleBounds)));
    if (index < 0) index = 0;
    if (index > [self numberOfPhotos] - 1) index = [self numberOfPhotos] - 1;
    NSUInteger previousCurrentPage = _currentIndex;
    _currentIndex = index;
    if (_currentIndex != previousCurrentPage) {
        NSLog(@"%lu/%li", (unsigned long)_currentIndex, (long)previousCurrentPage);
         [self startPageAtIndex:_currentIndex];
    }
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self updateNavTitle];
    [self displaySelectionButton];
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
   // [self setControlsHidden:YES animated:YES];
}
#pragma mark - SelectedButton
- (void)selectionButtonPressed
{
    if(_selectedButton.selected){
        [self setSelection:NO];
    }else{
        if(self.delegate && [self.delegate respondsToSelector:@selector(photoCanSelected:)]){
            if([self.delegate photoCanSelected:self.currentIndex]){
                [self setSelection:YES];
            }
        }
    }
}
- (void)setSelection:(BOOL)selection
{
    if(self.delegate && [self.delegate respondsToSelector:@selector(photoWithIndex:changeSelection:)])
    {
        [self.delegate photoWithIndex:self.currentIndex changeSelection:selection];
        [self displaySelectionButton];
    }
}
- (void)displaySelectionButton
{
    if(self.displaySelectionButtons){
        if(self.delegate && [self.delegate respondsToSelector:@selector(photoSelectionWithIndex:)])
            [_selectedButton setSelected:[self.delegate photoSelectionWithIndex:self.currentIndex]];
    }
    [_bottomBar setSelectedCount:[self.delegate photoDidSelectedCount]];
}
#pragma mark - Page

- (void)tilePages {
    
    // Calculate which pages should be visible
    // Ignore padding as paging bounces encroach on that
    // and lead to false page loads
    CGRect visibleBounds = _pagingScrollView.bounds;
    NSInteger iFirstIndex = (NSInteger)floorf((CGRectGetMinX(visibleBounds)+PADDING*2) / CGRectGetWidth(visibleBounds));
    NSInteger iLastIndex  = (NSInteger)floorf((CGRectGetMaxX(visibleBounds)-PADDING*2-1) / CGRectGetWidth(visibleBounds));
    if (iFirstIndex < 0) iFirstIndex = 0;
    if (iFirstIndex > [self numberOfPhotos] - 1) iFirstIndex = [self numberOfPhotos] - 1;
    if (iLastIndex < 0) iLastIndex = 0;
    if (iLastIndex > [self numberOfPhotos] - 1) iLastIndex = [self numberOfPhotos] - 1;
    
    // Recycle no longer needed pages
    NSInteger pageIndex;
    for (JHZoomingScrollView *page in _visiblePages) {
        pageIndex = page.index;
        if (pageIndex < (NSUInteger)iFirstIndex || pageIndex > (NSUInteger)iLastIndex) {
            [_recycledPages addObject:page];
            [page prepareForReuse];
            [page removeFromSuperview];

        }
    }
    [_visiblePages minusSet:_recycledPages];
    while (_recycledPages.count > 2) // Only keep 2 recycled pages
        [_recycledPages removeObject:[_recycledPages anyObject]];
    
    // Add missing pages
    for (NSUInteger index = (NSUInteger)iFirstIndex; index <= (NSUInteger)iLastIndex; index++) {
        if (![self isDisplayingPageForIndex:index]) {
            
            // Add new page
            JHZoomingScrollView *page = [self dequeueRecycledPage];
            if (!page) {
                page = [[JHZoomingScrollView alloc] initWithFrame:_pagingScrollView.bounds browser:self];
            }
            [_visiblePages addObject:page];
            [self configurePage:page forIndex:index];
            
            [_pagingScrollView addSubview:page];
        }
    }
    
}

- (void)configurePage:(JHZoomingScrollView *)page forIndex:(NSUInteger)index {
    page.frame = [self frameForPageAtIndex:index];
    page.index = index;

    [self.imageManager requestImageForAsset:self.assetArray[index] targetSize:[JHAssetsManager sizeOfPreview] contentMode:PHImageContentModeAspectFill options:[JHAssetsManager previewRequestOptions] resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        [page setPhoto:result];
    }];
}


- (JHZoomingScrollView *)dequeueRecycledPage {
    JHZoomingScrollView *page = [_recycledPages anyObject];
    if (page) {
        [_recycledPages removeObject:page];
    }
    return page;
}
- (BOOL)isDisplayingPageForIndex:(NSUInteger)index {
    for (JHZoomingScrollView *page in _visiblePages)
        if (page.index == index) return YES;
    return NO;
}

- (NSUInteger)numberOfPhotos {
    _photoCount = self.assetArray.count;
    return _photoCount;
}

#pragma mark - Frame Calculations

- (CGRect)frameForPagingScrollView {
    CGRect frame = self.view.bounds;// [[UIScreen mainScreen] bounds];
    frame.origin.x -= PADDING;
    frame.size.width += (2 * PADDING);
    return CGRectIntegral(frame);
}

- (CGRect)frameForPageAtIndex:(NSUInteger)index {
    // We have to use our paging scroll view's bounds, not frame, to calculate the page placement. When the device is in
    // landscape orientation, the frame will still be in portrait because the pagingScrollView is the root view controller's
    // view, so its frame is in window coordinate space, which is never rotated. Its bounds, however, will be in landscape
    // because it has a rotation transform applied.
    CGRect bounds = _pagingScrollView.bounds;
    CGRect pageFrame = bounds;
    pageFrame.size.width -= (2 * PADDING);
    pageFrame.origin.x = (bounds.size.width * index) + PADDING;
    return CGRectIntegral(pageFrame);
}

- (CGSize)contentSizeForPagingScrollView {
    // We have to use the paging scroll view's bounds to calculate the contentSize, for the same reason outlined above.
    CGRect bounds = _pagingScrollView.bounds;
    return CGSizeMake(bounds.size.width * [self numberOfPhotos], bounds.size.height);
}

- (CGPoint)contentOffsetForPageAtIndex:(NSUInteger)index {
    CGFloat pageWidth = _pagingScrollView.bounds.size.width;
    CGFloat newOffset = index * pageWidth;
    return CGPointMake(newOffset, 0);
}
#pragma mark - UINavigationControllerDelegate
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                            animationControllerForOperation:(UINavigationControllerOperation)operation
                                                         fromViewController:(UIViewController *)fromVC
                                                           toViewController:(UIViewController *)toVC
{
    if(operation == UINavigationControllerOperationPop)
        return [[PopAnimator alloc]init];
    return nil;
}
#pragma mark - 控制器 Hiding / Showing

- (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated
{
    _statusBarShouldBeHidden = hidden;
    
    CGFloat animationDuration = (animated ? 0.35 : 0);
    
    [UIView animateWithDuration:animationDuration animations:^(void) {
        [self setNeedsStatusBarAppearanceUpdate];
    } completion:^(BOOL finished) {}];
    
    [UIView animateWithDuration:animationDuration animations:^{
        CGFloat alpha = hidden?0.0f:1.0f;
        _bottomBar.alpha = alpha;
        CGFloat y = 44.0f;
        if(hidden){
            y = 0;
        }
        [self.bottomBar setFrame:CGRectMake(0, self.view.frame.size.height-y, self.view.frame.size.width, 44)];
        self.navigationController.navigationBar.alpha = alpha;
        [self.navigationController.navigationBar setUserInteractionEnabled:!hidden];
    }];
}
#pragma mark -  Enable/disable control visiblity timer
- (void)hideControls {
    [self setControlsHidden:YES animated:YES];
}
- (void)showControls {
    [self setControlsHidden:NO animated:YES];
}
- (void)toggleControls {
    [self setControlsHidden:![self areControlsHidden] animated:YES];
}
- (BOOL)areControlsHidden {
    return (self.navigationController.navigationBar.alpha == 0);
}

- (BOOL)prefersStatusBarHidden
{
    return _statusBarShouldBeHidden;
}
- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
    return UIStatusBarAnimationSlide;
}
#pragma mark - done
- (void)donePickViewController
{
    if(self.delegate && [self.delegate respondsToSelector:@selector(photoWithIndex:changeSelection:)])
    {
        [self.delegate photoWithIndex:_selectedIndex changeSelection:YES];
    }
    if(self.delegate && [self.delegate respondsToSelector:@selector(didSelectedDone)]){
        [self.delegate didSelectedDone];
    }
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
